package abg.core.common.util;

import jakarta.servlet.http.HttpServletResponse;

import java.io.*;
import java.util.Collections;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class ZipKit {

    /**
     * 写入Zip流
     *
     * @param os           输出流 OutputStream
     * @param fileNames    文件名称
     * @param inputStreams 输入流
     * @return 输出流 OutputStream
     */
    public static <T extends OutputStream> T zipToOs(T os, List<String> fileNames, List<? extends InputStream> inputStreams, int readSize) throws Exception {
        try (ZipOutputStream zos = new ZipOutputStream(os)) {
            writeFileList(zos, fileNames, inputStreams, readSize);
        }
        return os;
    }

    public static <T extends OutputStream> T zipToOs(T os, String fileName, InputStream inputStream, int readSize) throws Exception {
        return zipToOs(os, Collections.singletonList(fileName), Collections.singletonList(inputStream), readSize);
    }

    /**
     * 异步写入管道流
     *
     * @param pos          管道输出流 PipedOutputStream
     * @param fileNames    文件名称
     * @param inputStreams 输入流
     */
    public static void zipToPos(PipedOutputStream pos, List<String> fileNames, List<? extends InputStream> inputStreams, int readSize) {
        ThreadKit.getPool().execute(() -> {
            try (ZipOutputStream zos = new ZipOutputStream(pos)) {
                writeFileList(zos, fileNames, inputStreams, readSize);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    public static void zipToPos(PipedOutputStream pos, String fileName, InputStream inputStream, int readSize) {
        zipToPos(pos, Collections.singletonList(fileName), Collections.singletonList(inputStream), readSize);
    }

    /**
     * 写入下载流
     *
     * @param response 管道输出流 PipedOutputStream
     * @param zipName  文件名称
     * @param is       输入流
     */
    public static void download(HttpServletResponse response, String zipName, InputStream is, int readSize) throws Exception {
        download(response, Collections.singletonList(zipName), Collections.singletonList(is), readSize);
    }

    public static void download(HttpServletResponse response, List<String> zipNames, List<? extends InputStream> iss, int readSize) throws Exception {
        try (BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream())) {
            try (ZipOutputStream zos = new ZipOutputStream(bos)) {
                for (int i = 0; i < iss.size(); i++) {
                    zos.putNextEntry(new ZipEntry(zipNames.get(i)));
                    writeOs(zos, iss.get(i), readSize);
                    zos.closeEntry();
                }
            }
        }
    }

    public static void downloadLocal(FileOutputStream localStream, List<String> zipNames, List<? extends InputStream> iss, int readSize) throws Exception {
        try (BufferedOutputStream bos = new BufferedOutputStream(localStream)) {
            try (ZipOutputStream zos = new ZipOutputStream(bos)) {
                for (int i = 0; i < iss.size(); i++) {
                    zos.putNextEntry(new ZipEntry(zipNames.get(i)));
                    writeOs(zos, iss.get(i), readSize);
                    zos.closeEntry();
                }
            }
        }
    }

    public static void writeToOs(OutputStream o, List<String> zipNames, List<? extends InputStream> iss, int readSize) throws Exception {
        try (BufferedOutputStream bos = new BufferedOutputStream(o)) {
            try (ZipOutputStream zos = new ZipOutputStream(bos)) {
                for (int i = 0; i < iss.size(); i++) {
                    zos.putNextEntry(new ZipEntry(zipNames.get(i)));
                    writeOs(zos, iss.get(i), readSize);
                    zos.closeEntry();
                }
            }
        }
    }


    //私有方法，写流
    private static void writeOs(OutputStream os, InputStream is, int readSize) throws IOException {
        byte[] bytes = new byte[readSize];
        int size;
        while ((size = is.read(bytes)) != -1) {
            os.write(bytes, 0, size);
            os.flush();
        }
    }

    //私有方法，写入Zip流
    private static void writeFileList(ZipOutputStream zos, List<String> fileNames, List<? extends InputStream> inputStreams, int readSize) throws IOException {
        for (int i = 0; i < inputStreams.size(); i++) {
            //压缩包内的文件名
            zos.putNextEntry(new ZipEntry(fileNames.get(i)));
            try (BufferedInputStream bis = new BufferedInputStream(inputStreams.get(i))) {
                writeOs(zos, bis, readSize);
                zos.closeEntry();
            }
        }
    }

//    //返回压缩文件流
//    public static void getBaosBin(BufferedOutputStream baos, ZipOutputStream zos1, ZipOutputStream zos2) throws Exception {
//        try (ZipOutputStream endZos = new ZipOutputStream(baos)) {
//            //压缩包内的文件名
//            endZos.putNextEntry(new ZipEntry("最终文件.zip"));
//
//            try (ZipOutputStream zos = new ZipOutputStream(new ByteArrayOutputStream())) {
//                //循环将文件打进去
//                for (int i = 0; i < inputStreams.size(); i++) {
//                    //压缩包内的文件名
//                    zos.putNextEntry(new ZipEntry(fileNames.get(i)));
//
//                    try (BufferedInputStream bis = new BufferedInputStream(inputStreams.get(i))) {
//                        byte[] bytes = new byte[1024 * 1024];
//                        int size;
//                        while ((size = bis.read(bytes)) != -1) {
//                            zos.write(bytes, 0, size);
//                        }
//                        zos.closeEntry();
//                    }
//
//                }
//            }
//
//
//
//        }
//    }


}
